【X68000(Z)アセンブラ講座 第036回 スプライトダブラー(完成品版)】   こんにちは!! 前回のスプライトダブラー(試作品版)は理解できましたか? 前回のスプライトダブラーは不具合の出ない単純なスプライトの配置だったので256枚表示できましたが 今回は表示するスプライトの座標がランダム対応なので 不具合表示のスプライトをなるべく少なくするために32枚のスプライトを使うので 表示スプライト数は224枚になっています。 X68000Zや10MHzマシンではCPUの速度が遅いのでチラつくスプライトは多いです。 以下の破線の内側を'SPDBL_02.s'と言うファイル名で保存して下さい。 ------------------------------------------------------------------------------------------------ ******************************************************************************** * * アプリ名 : SPDBL_02.x * * スプライトダブラー(完成品版) * * Ver1.00 * ******************************************************************************** include A:\XC\INCLUDE\DOSCALL.MAC * OSコール用マクロの読み込み include A:\XC\INCLUDE\IOCSCALL.MAC * IOCS(BIOS)コール用マクロの読み込み sp_palette equ $E82200 * スプライト用パレットデータの先頭アドレス sp_pattern equ $EB8000 * スプライトパターンデータの先頭アドレス sp_controll equ $EB0000 * スプライトスクロールレジスターの先頭アドレス vsync equ $E88001 * %00010000でV-Syncチェックする vec_vdisp equ $000118 * V-DISP割り込み vec_hsync equ $00013C * H-SYNC割り込み * ラベルの定数定義 spx equ 0 spy equ 2 spnum equ 4 sppr equ 6 .cpu 68000 * CPUのタイプ .data * '.data'以降のデータはデータセクションに配置される .even vec118: dc.l 0 * V-Sync vec13C: dc.l 0 * H-Sync ras_num: dc.w 0 * Raster Number (現在処理中のラスター番号) sp01: * スプライトパターンデータ dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$02 dc.b $00,$00,$00,$23 dc.b $00,$00,$02,$34 dc.b $00,$00,$02,$34 dc.b $00,$00,$00,$23 dc.b $00,$00,$00,$02 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $20,$00,$00,$00 dc.b $32,$00,$00,$00 dc.b $43,$20,$00,$00 dc.b $43,$20,$00,$00 dc.b $32,$00,$00,$00 dc.b $20,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 dc.b $00,$00,$00,$00 sppal01: * GGGGG RRRRR BBBBB A dc.w %00000_00000_00000_0 dc.w %00000_00000_11111_0 dc.w %00000_11111_00000_0 dc.w %10000_11111_00000_0 dc.w %11111_11111_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %00000_00000_00000_0 dc.w %11111_11111_11111_0 .bss .even spbuf: ds.b 1792 * [spx,spy,spnum,priority]x224 (スプライトデータバッファ) spcnt: ds.w 1 * Sprite Counter (表示するスプライトの枚数 : 224) spbuf0: ds.b 1792 * スプライト表示用バッファ spbuf1: ds.b 1792 * スプライト表示用バッファ spbuf2: ds.b 1792 * スプライト表示用バッファ spcnt0: ds.w 1 * spbuf0のスプライトの個数 spcnt1: ds.w 1 * spbuf1のスプライトの個数 spcnt2: ds.w 1 * spbuf2のスプライトの個数 .text .even start: * スタートアドレス * ユーザーモードからスーパーバイザーモードに移行する moveq.l #_B_SUPER,d0 move.l #0,d1 movea.l d1,a1 trap #15 * カーソルをオフにする moveq.l #_OS_CUROF,d0 trap #15 * ランダム関数の初期化 move.l #12345,d0 * ランダムのシードを代入する(0 - 32767) dc.w $FE0D * ランダムのシードを設定する * 画面モードの設定 moveq.l #_CRTMOD,d0 move.w #10,d1 trap #15 * 画面をクリアして表示をオンにする moveq.l #_G_CLR_ON,d0 trap #15 * スプライト表示をオンにする moveq.l #_SP_ON,d0 trap #15 bsr set_palette * スプライトパレット設定ルーチンの呼び出し bsr def_sprite * スプライトパターンデータの定義ルーチンの呼び出し bsr init_chara * 表示スプライトのパターン定義 * V-DISP割り込みの設定 move.l vec_vdisp,vec118 * 現在の割り込みのアドレスをバックアップ lea int_vdisp,a0 * 割り込みとしてint_vdispルーチンのアドレスを move.l a0,vec_vdisp * 割り込みベクトルに登録する。 or.b #%01000000,$E88009 * V-DISP割り込みの許可の設定 or.b #%01000000,$E88015 * V-DISP割り込みのマスクの設定 and.b #%11101111,$E88003 * 垂直帰線期間で割り込み発生 * H-SYNC割り込みの設定 move.l vec_hsync,vec13C * 現在の割り込みのアドレスをバックアップ lea int_hsync,a0 * 割り込みとしてint_hsyncルーチンのアドレスを move.l a0,vec_hsync * 割り込みベクトルに登録する。 or.b #%10000000,$E88007 * H-SYNC割り込みの許可の設定 or.b #%10000000,$E88013 * H-SYNC割り込みのマスクの設定 and.b #%01111111,$E88003 * H-SYNC信号が'L'の時に割り込み発生 loop: * メインループ開始 * V-Syncビットを監視してメインループを60fpsで動作させるタイミングを取る movea.l #vsync,a0 vsync_1: move.b (a0),d0 and.b #$10,d0 tst.b d0 beq vsync_1 vsync_2: move.b (a0),d0 and.b #$10,d0 tst.b d0 bne vsync_2 bsr move_sprite bsr select_spbuf * スプライトデータを全てセットした後に呼び出す * [ESC]キーが押されたら終了処理'end:'にジャンプする moveq.l #_BITSNS,d0 moveq.l #0,d1 trap #15 and.b #%00000010,d0 tst.b d0 bne end bra loop * メインループの最初にジャンプする end: * V-DISP割り込みの終了処理 and.b #%10111111,$E88015 and.b #%10111111,$E88009 move.l vec118,vec_vdisp * H-SYNC割り込みの終了処理 and.b #%01111111,$E88007 or.b #%01111111,$E88013 move.l vec13C,vec_hsync moveq.l #_CRTMOD,d0 move.w #16,d1 trap #15 * カーソルをオンにする moveq.l #_OS_CURON,d0 trap #15 move.w #255,-(sp) dc.w _KFLUSH addq.l #2,sp * スーパーバイザーモードからユーザーモードに戻る moveq.l #_B_SUPER,d0 move.l SP,a1 trap #15 * アプリ終了 dc.w _EXIT int_vdisp: * V-DISP割り込みルーチン move.w #0,ras_num * 処理中ラスター番号の初期化 rte * スプライトを表示する割り込み int_hsync: * H-SYNC割り込みルーチン movem.l d0/d1/a0-a1,-(sp) cmp.w #0,ras_num bne int_hsync_1 lea spbuf1,a0 move.w spcnt1,d0 beq int_hsync_4 cmp.w #32,d0 ble int_hsync_0_0 moveq.l #32,d0 int_hsync_0_0: moveq.l #32,d1 sub.w d0,d1 cmp.w #0,d0 beq int_hsync_4 subq.w #1,d0 movea.l #sp_controll,a1 int_hsync_0_1: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbra d0,int_hsync_0_1 cmp.w #0,d1 beq int_hsync_4 subq.w #1,d1 int_hsync_0_2: move.w #0,spy(a1) addq.l #8,a1 dbra d1,int_hsync_0_2 bra int_hsync_4 int_hsync_1: cmp.w #28,ras_num bne int_hsync_2 lea spbuf0,a0 move.w spcnt0,d0 beq int_hsync_4 cmp.w #96,d0 ble int_hsync_1_0 moveq.l #96,d0 int_hsync_1_0: moveq.l #96,d1 sub.w d0,d1 cmp.w #0,d0 beq int_hsync_4 subq.w #1,d0 movea.l #sp_controll+256,a1 int_hsync_1_1: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbra d0,int_hsync_1_1 cmp.W #0,d1 beq int_hsync_4 subq.w #1,d1 int_hsync_1_2: move.w #0,spy(a1) addq.l #8,a1 dbra d1,int_hsync_1_2 bra int_hsync_4 int_hsync_2: cmp.w #256+48,ras_num bne int_hsync_4 lea spbuf2,a0 move.w spcnt2,d0 beq int_hsync_4 cmp.w #96,d0 ble int_hsync_2_1 moveq.l #96,d0 int_hsync_2_1: moveq.l #96,d1 sub.w d0,d1 cmp.w #0,d0 beq int_hsync_3_0 subq.w #1,d0 movea.l #sp_controll+256,a1 int_hsync_3: move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ dbra d0,int_hsync_3 int_hsync_3_0: cmp.w #0,d1 beq int_hsync_4 subq.w #1,d1 int_hsync_3_1: move.w #0,spy(a1) addq.l #8,a1 dbra d1,int_hsync_3_1 int_hsync_4: addq.w #1,ras_num * 処理するラスター番号の更新 movem.l (sp)+,d0/d1/a0-a1 rte * 全てのスプライトを1ドット下に移動する move_sprite: lea spbuf,a6 move.w #224,spcnt move.w spcnt,d7 beq move_sprite_e subq.w #1,d7 move_sprite_1: move.w spy(a6),d0 addq.w #1,d0 cmp.w #256+16,d0 blt move_sprite_2 moveq.l #0,d0 move_sprite_2: move.w d0,spy(a6) addq.l #8,a6 dbra d7,move_sprite_1 move_sprite_e: rts * スプライトのY座標を元に3つのスプライトバッファに振り分ける select_spbuf: lea spbuf,a6 lea spbuf0,a0 lea spbuf1,a1 lea spbuf2,a2 move.w #0,spcnt0 move.w #0,spcnt1 move.w #0,spcnt2 move.w spcnt,d7 beq select_spbuf_e subq.w #1,d7 select_spbuf_1: move.l (a6)+,d0 move.l (a6)+,d1 cmp.w #128,d0 bge select_spbuf_2 move.l d0,(a0)+ move.l d1,(a0)+ addq.w #1,spcnt0 bra select_spbuf_4 select_spbuf_2: cmp.w #160,d0 bge select_spbuf_3 move.l d0,(a1)+ move.l d1,(a1)+ addq.w #1,spcnt1 bra select_spbuf_4 select_spbuf_3: move.l d0,(a2)+ move.l d1,(a2)+ addq.w #1,spcnt2 select_spbuf_4: dbra d7,select_spbuf_1 select_spbuf_e: rts set_palette: movea.l #sp_palette,a0 adda.l #32,a0 lea sppal01,a1 moveq.l #0,d7 set_palette_1: move.w (a1)+,(a0)+ addq.w #1,d7 cmp.w #16,d7 blt set_palette_1 rts * スプライトパターンの定義 def_sprite: lea sp01,a0 movea.l #sp_pattern,a1 moveq.l #0,d7 def_sprite_1: move.l (a0)+,(a1)+ addq.w #1,d7 cmp.w #32,d7 blt def_sprite_1 rts * 複数キャラの初期化 init_chara: lea spbuf,a0 moveq.l #0,d7 init_chara_1: * X座標の初期値を決める dc.w $FE0E * d0.lに0から32767のランダム値を返す mulu #256+16,d0 divu #32767,d0 move.w d0,spx(a0) * Y座標の初期値を決める dc.w $FE0E mulu #256+16,d0 divu #32767,d0 move.w d0,spy(a0) * 表示するスプライトのパレット番号とスプライトパターン番号を設定する move.w #$0_1_00,spnum(a0) * 表示するスプライトのBG画面間(BG0/BG1)での表示優先順位 move.w #2,sppr(a0) addq.l #8,a0 addq.w #1,d7 cmp.w #224,d7 blt init_chara_1 rts * End Of File ------------------------------------------------------------------------------------------------ ファイルの保存が終わったらコマンドプロンプトから、 A>AS SPDBL_02.s [Enter] A>LK SPDBL_02.o [Enter} A>SPDBL_02.x [Enter] 以上(↑)のように入力するとプログラムが起動します。 今回は以上です(^^) お疲れ様でした!! [EOF]